package com.sina.rd.dsp.nedis;

import com.google.common.collect.Maps;
import com.sina.rd.dsp.protobuf.generated.ServerProtos;
import com.sina.rd.dsp.server.RouteMap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.HashMap;
import java.util.Properties;

import static com.sina.rd.dsp.protobuf.generated.ServerProtos.OperateCode;
/**
 * Created with IntelliJ IDEA.
 * User: xinrong3
 * Date: 14-4-3
 * Time: 上午11:31
 */
public class NedisServerHandler extends SimpleChannelInboundHandler<ServerProtos.ReqMessage> {
    public static final Log LOG = LogFactory.getLog(NedisServerHandler.class);

    private final Properties prop;
    private final HashMap<String,JedisPool> poolMap= Maps.newHashMap();
    private RouteMap routeMap;
    private JedisPool jedisPool;

    public NedisServerHandler(Properties properties,RouteMap map){
        super();
        this.prop=properties;
        this.routeMap=map;
    }

//    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ServerProtos.ReqMessage msg) throws Exception {
        OperateCode code=msg.getOperate();
        switch (code) {
            case SET:
                doSet(ctx,msg.getBid(),msg.getKey(),msg.getValue());
                break;
            case GET:
                doGet(ctx,msg.getBid(),msg.getKey());
                break;
            case EXSIT:
                doExist(ctx,msg.getBid(),msg.getKey());
                break;
        }
    }

    private void doSet(ChannelHandlerContext ctx, String bid, String key,String value) {
        JedisPool pool = getJedisPool(bid,key);
        if(pool==null){
            ctx.write(ServerProtos.RespMessage.newBuilder().setResult("null").build());
        }else{
            Jedis jedis=null;
            try {
                jedis=pool.getResource();
                ctx.write(ServerProtos.RespMessage.newBuilder().setResult(jedis.set(key,value)).build());
                pool.returnResource(jedis);
            }catch (Exception e){
                ctx.write(ServerProtos.RespMessage.newBuilder().setResult("null").build());
            }finally {
                pool.returnBrokenResource(jedis);
            }
        }
    }

    private void doExist(ChannelHandlerContext ctx, String bid, String key) {
        JedisPool pool = getJedisPool(bid,key);
        if(pool==null){
            ctx.write(ServerProtos.RespMessage.newBuilder().setResult("null").build());
        }else{
            Jedis jedis=null;
            try {
                jedis=pool.getResource();
                ctx.write(ServerProtos.RespMessage.newBuilder().setResult(String.valueOf(jedis.exists(key))).build());
                pool.returnResource(jedis);
            }catch (Exception e){
                ctx.write(ServerProtos.RespMessage.newBuilder().setResult("null").build());
            }finally {
                pool.returnBrokenResource(jedis);
            }
        }
    }

    private void doGet(ChannelHandlerContext ctx, String bid, String key) {
        JedisPool pool = getJedisPool(bid,key);
        if(pool==null){
            ctx.write(ServerProtos.RespMessage.newBuilder().setResult("null").build());
        }else{
            Jedis jedis=null;
            try {
                jedis=pool.getResource();
                ctx.write(ServerProtos.RespMessage.newBuilder().setResult(jedis.get(key)).build());
                pool.returnResource(jedis);
            }catch (Exception e){
                ctx.write(ServerProtos.RespMessage.newBuilder().setResult("null").build());
            }finally {
                pool.returnBrokenResource(jedis);
            }
        }
    }


    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        LOG.error(
                "Unexpected exception from downstream.", cause);
        ctx.close();
    }

    /**
     * 获取Jedis的资源池
     * @param bid bussiness id
     * @param key key
     * @return jedis pool
     */
    public JedisPool getJedisPool(String bid, String key) {
        String jedisKey=routeMap.getCache(bid,key);
        if(jedisKey!=null&&jedisKey.contains(":")){
            JedisPool pool=poolMap.get(jedisKey);
            if(pool==null){
                String part[]=jedisKey.split(":");
                try {
                    int jedisport=Integer.parseInt(part[1]);
                    pool=new JedisPool(part[0],jedisport);
                    poolMap.put(jedisKey,pool);
                }catch (NumberFormatException e){
                    LOG.error("route error,wrong cached key");
                }
            }
            return pool;
        }else{
            LOG.error("wrong route message,can not access");
        }
        return null;
    }

    @Override
    protected void messageReceived(ChannelHandlerContext channelHandlerContext, ServerProtos.ReqMessage reqMessage) throws Exception {

    }
}
